﻿using System;
/*
 Code Paragraph
 */
namespace ConsoleTest
{
    public class StreamTest
    {
        //通过静态类的方法来实现简单的文件读取
        //使用ReadAllText；ReadAllLines时需要考虑编码问题，如果编码格式不对则会出现乱码情况
        //Write等方法在文件不存在时将自行创建文件
        public static void SimpleFileAccess()
        {
            //System.Text.Encoding.Default  获取系统当前页的ANSI页编码
            string StrFileReadTxt = System.IO.File.ReadAllText("kewin.txt", System.Text.Encoding.Default);
            System.Console.WriteLine(StrFileReadTxt);
            System.IO.File.WriteAllText("kewinCopy.txt", StrFileReadTxt, System.Text.Encoding.Default);


            string[] StrArr = System.IO.File.ReadAllLines("kewin.txt", System.Text.Encoding.Default);
            System.Console.WriteLine(StrArr);
            System.IO.File.WriteAllLines("kewinCopy2.txt", StrArr, System.Text.Encoding.Default);

            byte[] byteArr = System.IO.File.ReadAllBytes("kewin.txt");
            System.Console.WriteLine(byteArr);
            System.IO.File.WriteAllBytes("kewinCopy3.txt", byteArr);
        }

        //使用数据流复制二进制文件
        public static void FileStreamCopy()
        {
            int bufferSize = 512;

            //默认应用程序域的友好名称是加载到应用程序域中的程序集文件的名称
            //实际就是程序集的名字取出路径字符串规范化后的结果
            string sExe = System.AppDomain.CurrentDomain.FriendlyName;
            
            //源文件和目标文件位于程序文件夹内

            System.IO.FileStream inStream = System.IO.File.OpenRead(sExe);
            
            System.IO.FileStream outStream = System.IO.File.OpenWrite("Copy.exe");

            byte[] buffer = new System.Byte[bufferSize];

            int nBytesRead = 0;


            while( (nBytesRead=inStream.Read(buffer,0,bufferSize))>0)
                outStream.Write(buffer,0,nBytesRead);

            inStream.Close();
            outStream.Close();

        }

        //使用类型化的流类进行文件复制操作
        public static void StreamWRCopyFile()
        {
            //StreamReader 实现一个 TextReader，使其以一种特定的编码从字节流中读取字符。
            //该类旨在使用指定的编码格式读取
            //StreamReader 的默认编码为 UTF-8，而不是当前系统的 ANSI 代码页。UTF-8 可以正确处理 Unicode 字符并在操作系统的本地化版本上提供一致的结果。

            //OpenText 打开现有 UTF-8 编码文本文件以进行读取。且该方法返回 StreamReader 对象
            //注意：如果文本文件的格式为其他编码格式，会出现乱码，比如 ANSI编码格式等
            System.IO.StreamReader inStream = System.IO.File.OpenText("kewinUTF8.txt");
            
            System.Console.WriteLine("Encoding Type is: " + inStream.CurrentEncoding);

            System.IO.StreamWriter outStream = new System.IO.StreamWriter("kewinCopyByStreamWriter.txt", false,System.Text.Encoding.Default);

            string strTmp;
            while ((strTmp = inStream.ReadLine()) != null)
            {
                System.Console.WriteLine(strTmp);
                outStream.WriteLine(strTmp);
            }


            //释放资源
            inStream.Close();
            outStream.Close();
        }


        #region 异步方式操作流
        //首先创建一份大小为10Mb的文件
        //然后在循环中利用BeginRead异步方法对文件进行NRead次的读写
        //文件的异步读写全部线程来自CLR线程池


        //
        class FileStatus
        {
            public byte[] Buffer;
            public System.IO.FileStream Fs;
            public int Id;
        }

        static readonly int NByersPerFile = 10000000;
        static readonly int NRead = 5;
        static string FileName = "Blob.bin";
        
        //异步方式操作流
        public static void AccessStreamAsync()
        {
            CreateBlobFile();

            for (int i = 0; i < NRead; i++)
            {
                System.IO.FileStream fs = new System.IO.FileStream(FileName, System.IO.FileMode.Open, System.IO.FileAccess.Read
                    , System.IO.FileShare.Read, 4096, true);

                FileStatus status = new FileStatus();

                status.Id = i;
                status.Fs = fs;
                status.Buffer=new byte[NByersPerFile];


                System.Console.WriteLine("Thread #{0}: trigger asynchronous read  #{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, status.Id);

                fs.BeginRead(status.Buffer, 0, NByersPerFile, new AsyncCallback(CallBackOnReadDone), status);
                
            }

            System.Threading.Thread.Sleep(10000);
        }
        //创建文件
        static void CreateBlobFile()
        {
            byte[] blob=new byte[NByersPerFile];
            System.IO.FileStream fs = new System.IO.FileStream(FileName, System.IO.FileMode.Create, System.IO.FileAccess.Write
                , System.IO.FileShare.None, 4096, false);

            fs.Write(blob, 0, NByersPerFile);
            fs.Flush();
            fs.Close();
        }
        //文件读取结束时回调方法
        static void CallBackOnReadDone(System.IAsyncResult asyncResult)
        {
            FileStatus status = asyncResult.AsyncState as FileStatus;
            byte[] data = status.Buffer;
            System.IO.FileStream fs = status.Fs;

            //等待异步调用结束
            int nByesRead = fs.EndRead(asyncResult);
            fs.Close();

            System.Console.WriteLine("Thread #{0}: begin work on data #{1}",System.Threading.Thread.CurrentThread.ManagedThreadId,status.Id);

            System.Threading.Thread.Sleep(1000);

            System.Console.WriteLine("Thread #{0}: end work on data #{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, status.Id);
        }
        #endregion 异步方式操作流


        #region 文件写终端回滚
       public static void CreateBlobFileTest()
        {
            byte[] blob = new byte[NByersPerFile];
            System.IO.FileStream fs = new System.IO.FileStream(FileName, System.IO.FileMode.Create, System.IO.FileAccess.Write
                , System.IO.FileShare.None, 4096, false);
            using (System.Transactions.TransactionScope scop = new System.Transactions.TransactionScope())
            {
                bool IsSuccess = false;
                try
                {
                    for (int i = 0; i < 10; i++)
                    {
                        fs.Write(blob, i * (NByersPerFile / 10), NByersPerFile / 10);
                        if (i > 5)
                            throw new Exception("文件写入到" + ((float)i / 10) * 100 + "%时发生异常！");
                    }
                    IsSuccess = true;
                    
                }
                catch (Exception e)
                {
                    System.Console.WriteLine(e.Message);
                }
                finally
                {
                    fs.Flush();
                    fs.Close();
                    if (IsSuccess)
                        scop.Complete();
                }
            }
        }
        #endregion 


    }
}